﻿using Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Linguist.Acoustic
{
    /// <summary>
    /// Represents  the context for a unit 
    /// </summary>
    public class LeftRightContext : Context
    {
        
        String stringRepresentation;
        IUnit[] leftContext;
        IUnit[] rightContext;

        /**
        /// Creates a LeftRightContext
         *
        /// @param leftContext  the left context or null if no left context
        /// @param rightContext the right context or null if no right context
         */
        private LeftRightContext(IUnit[] leftContext, IUnit[] rightContext) {
            this.leftContext = leftContext;
            this.rightContext = rightContext;
        }

        /** Provides a string representation of a context */
        override
        public String ToString() 
        {
            return getContextName(leftContext) + ',' + getContextName(rightContext);
        }

        /**
        /// Factory method for creating a left/right context
         *
        /// @param leftContext  the left context or null if no left context
        /// @param rightContext the right context or null if no right context
        /// @return a left right context
         */
        public static LeftRightContext get(IUnit[] leftContext, IUnit[] rightContext) 
        { 
            return new LeftRightContext(leftContext, rightContext);
        }

        /**
        /// Retrieves the left context for this unit
         *
        /// @return the left context
         */
        public IUnit[] getLeftContext() 
        {
            return leftContext;
        }

        /**
        /// Retrieves the right context for this unit
         *
        /// @return the right context
         */
        public IUnit[] getRightContext() 
        {
            return rightContext;
        }

        /**
        /// Gets the context name for a particular array of units
         *
        /// @param context the context
        /// @return the context name
         */
        public static String getContextName(IUnit[] context) 
        {
            if (context == null)
                return "*";
            if (context.Length == 0)
                return "(empty)";
            StringBuilder sb = new StringBuilder();
            foreach (Unit unit in context) 
            {
                sb.Append(unit == null ? null : unit.getName()).Append('.');
            }
            sb.Length = sb.Length - 1; // remove last period
            return sb.ToString();
        }

        /**
        /// Checks to see if there is a partial match with the given context. If both contexts are LeftRightContexts then  a
        /// left or right context that is null is considered a wild card and matches anything, othewise the contexts must
        /// match exactly. Anything matches the Context.EMPTY_CONTEXT
         *
        /// @param context the context to check
        /// @return true if there is a partial match
         */
        public Boolean isPartialMatch(Context context) 
        {
            if (context is LeftRightContext) 
            {
                LeftRightContext lrContext = (LeftRightContext)context;
                IUnit[] lc = lrContext.getLeftContext();
                IUnit[] rc = lrContext.getRightContext();

                return (lc == null || leftContext == null || Unit.isContextMatch(lc, leftContext))
                    && (rc == null || rightContext == null || Unit.isContextMatch(rc, rightContext));
            }
            return context == Context.EMPTY_CONTEXT && leftContext == null && rightContext == null;
        }
    }
}
